﻿using System;

namespace LinqExtender.Tests
{
    public class ExpressionVisitor
    {
        public Ast.Expression Visit(Ast.Expression expression)
        {
            switch (expression.CodeType)
            {
                case CodeType.LambdaExpresion:
                    return this.VisitLambdaExpression((Ast.LambdaExpression)expression);
                case CodeType.LogicalExpression:
                    return this.VisitLogicalExpression((Ast.LogicalExpression)expression);
                case CodeType.BinaryExpression:
                    return this.VisitBinaryExpression((Ast.BinaryExpression)expression);
                case CodeType.LiteralExpression:
                    return this.VisitLiteralExpression((Ast.LiteralExpression)expression);
                case CodeType.SimpleExpression:
                    return this.VisitParameterExpression((Ast.SimpleExpression)expression);
                case CodeType.MemberExpression:
                    return this.VisitMemberExpression((Ast.MemberExpression)expression);

            }

            throw new ArgumentException("Expression type is not supported");
        }

        public virtual Ast.Expression VisitLogicalExpression(Ast.LogicalExpression expression)
        {
            this.Visit(expression.Left);
            this.Visit(expression.Right);
            return expression;
        }

        public virtual Ast.Expression VisitLambdaExpression(Ast.LambdaExpression expression)
        {
            return this.Visit(expression.Body);
        }

        public virtual Ast.Expression VisitBinaryExpression(Ast.BinaryExpression expression)
        {
            this.Visit(expression.Left);
            this.Visit(expression.Right);

            return expression;
        }

        public virtual Ast.Expression VisitParameterExpression(Ast.SimpleExpression expression)
        {
            return expression;
        }

        public virtual Ast.Expression VisitMemberExpression(Ast.MemberExpression expression)
        {
            return expression;
        }

        public virtual Ast.Expression VisitLiteralExpression(Ast.LiteralExpression expression)
        {
            return expression;
        }

    }
}
